package com.hspedu.seckill.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hspedu.seckill.pojo.Order;
import com.hspedu.seckill.pojo.SeckillMessage;
import com.hspedu.seckill.pojo.SeckillOrder;
import com.hspedu.seckill.pojo.User;
import com.hspedu.seckill.rabbitmq.MQSenderMessage;
import com.hspedu.seckill.service.GoodsService;
import com.hspedu.seckill.service.OrderService;
import com.hspedu.seckill.service.SeckillOrderService;
import com.hspedu.seckill.vo.GoodsVo;
import com.hspedu.seckill.vo.RespBean;
import com.hspedu.seckill.vo.RespBeanEnum;
import com.ramostear.captcha.HappyCaptcha;
import com.ramostear.captcha.common.Fonts;
import com.ramostear.captcha.support.CaptchaStyle;
import com.ramostear.captcha.support.CaptchaType;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("/seckill")
public class SeckillController implements InitializingBean {

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private SeckillOrderService seckillOrderService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MQSenderMessage mqSenderMessage;

    //定义map记录是否还有库存
    private Map<Long,Boolean> entryStockMap = new HashMap<>();

    //生成验证码
    @RequestMapping("/captcha")
    public void happyCaptcha(HttpServletRequest request, HttpServletResponse response,User user,Long goodsId){

        //生成验证码,验证码默认保存在Session，key为happy-captcha
        HappyCaptcha.require(request, response)
                .style(CaptchaStyle.ANIM) //设置展现样式为动画
                .type(CaptchaType.NUMBER) //设置验证码内容为数字
                .length(6) //设置字符长度为 6
                .width(220) //设置动画宽度为 220
                .height(80) //设置动画高度为 80
                .font(Fonts.getInstance().zhFont()) //设置汉字的字体
                .build().finish(); //生成并输出验证码

        redisTemplate.opsForValue().set("captcha:" + user.getId() + ":" + goodsId,
                (String)request.getSession().getAttribute("happy-captcha"),100, TimeUnit.SECONDS);
    }


    @RequestMapping("/path")
    @ResponseBody
    public RespBean getPath(User user,Long goodsId,String captcha){
        if(user == null || goodsId < 0)
            return RespBean.error(RespBeanEnum.SESSION_ERROR);

        boolean check = orderService.checkCaptcha(user, goodsId, captcha);

        if(check == false){
            return RespBean.error(RespBeanEnum.REQUEST_ILLEGAL);
        }

        String path = orderService.createPath(user,goodsId);
        return RespBean.success(path);
    }

    //处理用户秒杀请求
    @RequestMapping("/{path}/doSeckill")
    @ResponseBody
    public RespBean doSeckill(@PathVariable String path, Model model, User user, Long goodsId){

        /*  秒杀V2.0 */
        if(user == null)
            return RespBean.error(RespBeanEnum.SESSION_ERROR);

        //判断路径是否正确
        boolean check = orderService.checkPath(user, goodsId, path);
        if(!check){
            return RespBean.error(RespBeanEnum.REQUEST_ILLEGAL);
        }


        GoodsVo goodsVo = goodsService.findGoodsVoByGoodsId(goodsId);


        //判断库存
        if(!entryStockMap.get(goodsId)){
            return RespBean.error(RespBeanEnum.ENTRY_STOCK);
        }

        //判断复购
        SeckillOrder seckillOrder = (SeckillOrder)redisTemplate.
                opsForValue().get("order:" + user.getId() + ":" + goodsVo.getId());
        if (seckillOrder != null){
            return RespBean.error(RespBeanEnum.REPEAT_ERROR);
        }

        //从Redis实现库存删减，只有抢购成功的才可以进行走到后续操作，减少DB操作
        //Redis decrement具有原子性
        Long decrement = redisTemplate.opsForValue().decrement("seckillGoods:" + goodsId);
        if(decrement < 0){

            //没有库存了
            entryStockMap.put(goodsId,false);

            //恢复为0
            redisTemplate.opsForValue().increment("seckillGoods:" + goodsId);
            return RespBean.error(RespBeanEnum.ENTRY_STOCK);
        }

/*
        //抢购
        Order order = orderService.seckill(user, goodsVo);
        if(order == null){
            model.addAttribute("errmsg",RespBeanEnum.UNEXIST_ERROR.getMessage());
            return "secKillFail";
        }

        //进入订单页
        model.addAttribute("order",order);
        model.addAttribute("goods",goodsVo);

        return "orderDetail";

*/
        //V4.0
        //发送秒杀消息后，立马返回即时消息，等待轮询出最终结果
        SeckillMessage message = new SeckillMessage(user,goodsId);
        mqSenderMessage.sendSeckillMessage(JSONUtil.toJsonStr(message));
        return RespBean.error(RespBeanEnum.SECKILL_WAIT);


    }

    //实现InitializingBean类后，此方法可以在类的所有属性初始化后自动执行
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> list = goodsService.findGoodsVo();
        if(CollectionUtils.isEmpty(list)){
            return;
        }

        //遍历list,将秒杀库存存入Redis
        //格式为 seckillGoods:商品id
        list.forEach(goodsVo -> {
            redisTemplate.opsForValue()
                    .set("seckillGoods:" + goodsVo.getId(),goodsVo.getStockCount());

            //true有库存 false无库存
            if(goodsVo.getStockCount() > 0)
                entryStockMap.put(goodsVo.getId(),true);
            else
                entryStockMap.put(goodsVo.getId(),false);
        });

    }
}
